#include "carcount.h"
#include "ui_carcount.h"

#include <QMouseEvent>
#include <QPainter>
#include <QDebug>
#include <math.h>

static int button_status = 1;
static int h = 0;
static int w = 0;

#define height_h 100
#define width_w 100

enum {NO_1,NO_2,NO_3};
static int button_Num = NO_1;
static enum mouseStatus{mouseLeft,mouseRight} mouseClick;

CarCount::CarCount(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::CarCount)
{
    ui->setupUi(this);
    //运动对象背景分离对象
//    bgKNN = cv::createBackgroundSubtractorKNN();

    bgMOG2 = cv::createBackgroundSubtractorMOG2();
    bgMOG2->setVarThreshold(50);  //方差阈值，主要用于判断前景还是背景

    //打开视频(绝对路径)
    //cap.open("E:/QtCarCount/test.mp4");//打开本地视频
    //cap.open("/mnt/jeking/Car/test_1.mov");//打开本地视频
    cap.open("E:/QtCarCount/test_1.mp4");//打开本地视频

    //初始化ui数组
    ui->label->installEventFilter( this );
    x=y=x2=y2=x_1=y_1=x_2=y_2=x_3=y_3=0;
    startTimer(50);
    //打开摄像头设备(笔记本自带为0,USB外接为7)
//    this->cap.open(7);

}

CarCount::~CarCount()
{
    delete ui;
}

//鼠标按下
void CarCount::mousePressEvent(QMouseEvent *e)
{
    // 如果是鼠标左键按下，选择绘制位置
    if(e->button() == Qt::LeftButton)
    {
        w = 100;
        h = 50;

        if (button_status == 0)
            return;
        if(button_Num==NO_1)
        {
            x = x_1 = e->pos().x() - 10;
            y = y_1 = e->pos().y() - 10;
            ui->x1Lb->setText(QString::number(x));
            ui->y1Lb->setText(QString::number(y));


            ui->x2Lb->setText(QString::number(x+80));
            ui->y2Lb->setText(QString::number(y+50));

        }

        if(button_Num==NO_2)
        {
            x = x_2 = e->pos().x() - 10;
            y = y_2 = e->pos().y() - 10;
            ui->x1Lb_2->setText(QString::number(x));
            ui->y1Lb_2->setText(QString::number(y));


            ui->x2Lb_2->setText(QString::number(x+80));
            ui->y2Lb_2->setText(QString::number(y+50));

        }

        if(button_Num==NO_3)
        {
            x = x_3 = e->pos().x() - 10;
            y = y_3 = e->pos().y() - 10;
            ui->x1Lb_3->setText(QString::number(x));
            ui->y1Lb_3->setText(QString::number(y));


            ui->x2Lb_3->setText(QString::number(x+80));
            ui->y2Lb_3->setText(QString::number(y+50));

        }



    }
    // 如果是鼠标右键按下，确认
    else if(e->button() == Qt::RightButton)
    {
        mouseClick = mouseRight;
        if (button_Num < NO_3)
        {
            button_Num ++;

        }
        else
        {
            button_status = 0;
        }
    }
    // 如果是鼠标中键按下,取消
    else if(e->button() == Qt::MidButton)
    {

    }
}

// 鼠标移动事件
void CarCount::mouseMoveEvent(QMouseEvent *)
{
    //    x2 = e->pos().x();
    //    y2 = e->pos().y();
    //在ui->x2Lb中显示x2的值
    //    ui->x2Lb->setText(QString::number(x2));
    //    ui->y2Lb->setText(QString::number(y2));
    //    update();
}

void CarCount::paint()
{

}

bool CarCount::eventFilter(QObject *obj, QEvent *e)
{
    if(e->type() == QEvent::Paint)
    {
        paint();
    }
    return QMainWindow::eventFilter(obj,e);
}

void CarCount::timerEvent(QTimerEvent *)
{

    //采集一帧数据
    cv::Mat FrameImage;
    cap.read(FrameImage);
    //转大小
    cv::Mat newImage;
    //与界面显示一样
    //ARM开发板用↓
//        cv::resize(FrameImage, newImage, cv::Size(200,200));
    //Windows用↓
    cv::resize(FrameImage, newImage, cv::Size(ui->label->rect().width(),ui->label->height()));
    //resize(输入原图像，即待改变大小的图像,输出改变后的图像, 输出图像的大小)缩小或者放大函数至某一个大小


    //    cv::Rect rect(x,y,abs(x2-x),abs(y2-y));//检测区域rect(矩形左上角起始坐标的x，矩形左上角起始坐标的y，宽，高)
    cv::Rect rect_1;
    cv::Rect rect_2;
    cv::Rect rect_3;

    if(button_Num == NO_1)
    {
        rect_1.x = x_1;
        rect_1.y = y_1;
        rect_1.width = height_h;
        rect_1.height = width_w;
        cv::rectangle(newImage,rect_1,cv::Scalar(255,0,0));//画检测区域线(,设置颜色为红色)
    }

    if(button_Num == NO_2)
    {
        rect_1.x = x_1;
        rect_1.y = y_1;
        rect_1.width = height_h;
        rect_1.height = width_w;
        cv::rectangle(newImage,rect_1,cv::Scalar(255,0,0));//画检测区域线(,设置颜色为红色)

        rect_2.x = x_2;
        rect_2.y = y_2;
        rect_2.width = height_h;
        rect_2.height = width_w;
        //检测区域rect(矩形左上角起始坐标的x，矩形左上角起始坐标的y，宽，高)
        cv::rectangle(newImage,rect_2,cv::Scalar(255,0,0));//画检测区域线(,设置颜色为红色)
    }

    if(button_Num == NO_3)
    {
        //        cv::Rect rect_2(x,y,100,50);
        rect_1.x = x_1;
        rect_1.y = y_1;
        rect_1.width = height_h;
        rect_1.height = width_w;
        cv::rectangle(newImage,rect_1,cv::Scalar(255,0,0));//画检测区域线(,设置颜色为红色)

        rect_2.x = x_2;
        rect_2.y = y_2;
        rect_2.width = height_h;
        rect_2.height = width_w;
        //检测区域rect(矩形左上角起始坐标的x，矩形左上角起始坐标的y，宽，高)
        cv::rectangle(newImage,rect_2,cv::Scalar(255,0,0));//画检测区域线(,设置颜色为红色)

        rect_3.x = x_3;
        rect_3.y = y_3;
        rect_3.width = height_h;
        rect_3.height = width_w;
        cv::rectangle(newImage,rect_3,cv::Scalar(255,0,0));//画检测区域线(,设置颜色为红色)
    }

    //    cv::Rect rect_3(x,y,100,50);//检测区域rect(矩形左上角起始坐标的x，矩形左上角起始坐标的y，宽，高)
    //    cv::rectangle(newImage,rect_3,cv::Scalar(255,0,0));//画检测区域线(,设置颜色为红色)


    //在qt界面显示图像
    QImage image=QImage(newImage.data,newImage.cols,newImage.rows,newImage.step,QImage::Format_BGR888);
    ui->label->setPixmap(QPixmap::fromImage(image));
//    QImage image=QImage(newImage.data,newImage.cols,newImage.rows,newImage.step,QImage::Format_RGB888);
//    QPixmap pix;
//    ui->label->setPixmap(pix.fromImage(image).scaled(ui->label->rect().width(),ui->label->rect().height()));
update();

    //转灰度
    cv::Mat grayImage;
    cv::cvtColor(newImage, grayImage, cv::COLOR_RGB2GRAY);  //转换为灰度图
    cv::blur(grayImage, grayImage, cv::Size(3, 3));		//使用平滑运算

    //使用MOG2算法提取前景
    cv::Mat outImage;
    //使用KNN算法提取前景
//    bgKNN->apply(grayImage,outImage,-1);
    //使用MOG2算法提取前景
    bgMOG2->apply(grayImage,outImage,-1);
    if(mouseClick == mouseRight)
    {
        static double T1=0,T2=0;
        //开始算法计时
        T1 = (double)cv::getCPUTickCount();
        if(!outImage.empty())
        {
            cv::Mat showMat;
            outImage.copyTo(showMat);
            //*****************************************  1  ***********************************
            if (button_Num == NO_1||button_Num == NO_2||button_Num == NO_3)
            {
                // 1
                cv::Mat subMat = outImage(rect_1);	//再MOG2的前景提取结果中，取车道标记矩形框区域为subMat矩阵
                cv::Mat sumMat;		//积分图 == subMat的积分矩阵
                cv::integral(subMat, sumMat, CV_32S);		//设置积分矩阵的数据类型为int；
                int sumValue = (int)sumMat.at<int>((int)sumMat.rows - 1, (int)sumMat.cols - 1);  //获取积分图右下角的值，就是矩形框内亮度和；


                //循环打印判断
//                qDebug()<<"*****NO.1******"<<sumValue;
                static int flag_time = 0;
                static double t1=0,t2=0;
                static int LanneLightSum_prev;			//车道亮度和：上一帧的
                if(sumValue > 500000)
                {
                    if(flag_time== 0)
                    {
                        //开始计时
                        t1 = (double)cv::getCPUTickCount();
                        flag_time = 1;
                    }
                }

                if (LanneLightSum_prev > 500000  && sumValue <= 500000)
                {
                    if(flag_time== 1)
                    {
                        //结束计时
                        t2 = (double)cv::getCPUTickCount();
                        flag_time = 0;
                    }

                    //:: 车辆通过了矩形框：上一帧亮度和大于阈值，本帧亮度和小于阈值；车辆计数器自加；
                    ++LanneCarCnt;
                    LanneLightSum_prev= sumValue;
                    // 时间计算
                    ui->time1Lb->setText(QString("%1ms").arg((int)(1e0 *(t2-t1)/(double)cv::getTickFrequency())));
                    //结束算法计时
                    T2 = (double)cv::getCPUTickCount();
                    qDebug()<<"*****MOG2******"<<(int)(1e0 *(t2-t1)/(double)cv::getTickFrequency());
                }
                else
                    LanneLightSum_prev = sumValue;  //存储当前亮度和到LanneLightSum_prev


//                qDebug()<<"NO.1:"<<LanneCarCnt;
                ui->pass1Lb->setText(QString::number(LanneCarCnt));
                //速度计算
                int speed = (int)(3.0/((1e0 *(t2-t1)/(double)cv::getTickFrequency())*(1e-3)))*3.6;
                if(speed > 0)
                    ui->label_9->setText(QString("%1km/h").arg(speed));

            }
            //*****************************************  2  ***********************************
            if(button_Num == NO_2||button_Num == NO_3)
            {
                // 2
                cv::Mat subMat = outImage(rect_2);	//再MOG2的前景提取结果中，取车道标记矩形框区域为subMat矩阵
                cv::Mat sumMat;		//积分图 == subMat的积分矩阵
                cv::integral(subMat, sumMat, CV_32S);		//设置积分矩阵的数据类型为int；
                int sumValue = (int)sumMat.at<int>((int)sumMat.rows - 1, (int)sumMat.cols - 1);

//                qDebug()<<"*****NO.2******"<<sumValue;
                static int flag_time = 0;
                static    double t1=0,t2=0;
                static int LanneLightSum_prev;
                if(sumValue > 500000)
                {
                    if(flag_time == 0)
                    {
                        //开始计时
                        t1 = (double)cv::getCPUTickCount();//getTickCount()：用于返回从操作系统启动到当前所经的计时周期数
                        flag_time = 1;
                    }

                }

                if (LanneLightSum_prev > 500000  && sumValue <= 500000)
                {
                    if(flag_time == 1)
                    {
                        //结束计时
                        t2 = (double)cv::getCPUTickCount();
                        flag_time = 0;
                    }

                    //:: 车辆通过了矩形框：上一帧亮度和大于阈值，本帧亮度和小于阈值；车辆计数器自加；
                    ++LanneCarCnt_2;
                    LanneLightSum_prev= sumValue;
                    // 时间计算
                    ui->time1Lb_2->setText(QString("%1ms").arg((int)(1e0 *(t2-t1)/(double)cv::getTickFrequency())));
                }
                else
                    LanneLightSum_prev = sumValue;  //存储当前亮度和到LanneLightSum_prev

//                qDebug()<<"NO.2:"<<LanneCarCnt_2;
                ui->pass1Lb_2->setText(QString::number(LanneCarCnt_2));
                //速度计算
                int speed = (int)(3.0/((1e0 *(t2-t1)/(double)cv::getTickFrequency())*(1e-3)))*3.6;
                if(speed > 0)
                    ui->label_7->setText(QString("%1km/h").arg(speed));
            }
            //*****************************************  3  ***********************************
            if (button_Num == NO_3)
            {
                // 1
                cv::Mat subMat = outImage(rect_3);	//再MOG2的前景提取结果中，取车道标记矩形框区域为subMat矩阵
                cv::Mat sumMat;		//积分图 == subMat的积分矩阵
                cv::integral(subMat, sumMat, CV_32S);		//设置积分矩阵的数据类型为int；
                int sumValue = (int)sumMat.at<int>((int)sumMat.rows - 1, (int)sumMat.cols - 1);  //获取积分图右下角的值，就是矩形框内亮度和；


                //循环打印判断
                qDebug()<<"*****NO.3******"<<sumValue;
                static int flag_time_1 = 0;
                static    double t1=0,t2=0;
                static int LanneLightSum_prev;
                if(sumValue > 500000)
                {
                    if(flag_time_1 == 0)
                    {
                        //开始计时
                        t1 = (double)cv::getCPUTickCount();
                        flag_time_1 = 1;
                    }

                }

                if (LanneLightSum_prev > 500000  && sumValue <= 500000)
                {
                    if(flag_time_1 == 1)
                    {
                        //结束计时
                        t2 = (double)cv::getCPUTickCount();
                        flag_time_1 = 0;
                    }

                    //:: 车辆通过了矩形框：上一帧亮度和大于阈值，本帧亮度和小于阈值；车辆计数器自加；
                    ++LanneCarCnt_3;
                    LanneLightSum_prev= sumValue;
                    // 时间计算
                    ui->time1Lb_3->setText(QString("%1ms").arg((int)(1e0 *(t2-t1)/(double)cv::getTickFrequency())));
                    //                    ui->time1Lb_3->setNum(1e0 *(t2-t1)/(double)cv::getTickFrequency());
                }
                else
                    LanneLightSum_prev = sumValue;  //存储当前亮度和到LanneLightSum_prev


                qDebug()<<"NO.3:"<<LanneCarCnt_3;
                ui->pass1Lb_3->setText(QString::number(LanneCarCnt_3));
                //速度计算
                int speed = (int)(3.0/((1e0 *(t2-t1)/(double)cv::getTickFrequency())*(1e-3)))*3.6;
                if(speed > 0)
                    ui->label_10->setText(QString("%1km/h").arg(speed));
            }
            ui->label_3->setText(QString::number(LanneCarCnt+LanneCarCnt_2+LanneCarCnt_3));//车辆总数
        }
    }
}
